import shengMubiao from './lib/shengMubiao.js';
import yunMuBiao from './lib/yunMuBiao.js';
import zhengTiRenDuYinJieBiao from './lib/zhengTiRenDuYinJieBiao.js';
import ziMuBiao from './lib/ziMuBiao.js';
let shuZiBiao = createShuZiBiao();

let currentBiao = ziMuBiao;
let currentList = [];

const $container = document.querySelector('#container');
const $refreshBtn = document.querySelector('#refresh');
const $typeSelector = document.querySelector('#type');
const $lengthOfSide = document.querySelector('#lengthOfSide');
const $maxNumWrap = document.querySelector('#maxNumWrap');
const $maxNum = document.querySelector('#maxNum');
const $tableNum = document.querySelector('#tableNum');
const $print = document.querySelector('#print');

/**
 * 创建数字表
 * @param {number} max 最大数
 * @returns 数字表
 */
function createShuZiBiao(max = 100) {
  const shuZiBiao = [];
  for (let i = 0, limit = max; i < limit; i++) {
    shuZiBiao.push(i);
  }
  return shuZiBiao;
}

/**
 * 根据边长，从原始数据列表中随机截取数组
 * @param {string[] | number[]} originList 原始数据列表
 * @param {number} lengthOfSide 整数边长
 * @returns 打乱顺序后的数据列表
 */
function randomList(originList, lengthOfSide = 3) {
  const total = originList.length;
  if (total < lengthOfSide * lengthOfSide) {
    throw '边数过长，列表长度不够';
  }
  const length = lengthOfSide * lengthOfSide;
  const residue = total - length;
  const startIndex = randomInt(residue);
  return originList.slice(startIndex, startIndex + length);
}

/**
 * 数组乱序
 * @param {any[]} arr 原始数组
 * @returns 打乱顺序的数组
 */
function shuffle(arr) {
  const newArr = [...arr];
  return newArr.sort(() => Math.random() - 0.5);
}

/**
 * 生成指定范围的随机整数
 * @param {number} max 最大值，默认为100，取不到该数值
 * @param {number} min 最小值，默认为0
 * @returns 返回大于等于最小值，小于最大值的随机数
 */
function randomInt(max = 100, min = 0) {
  const randomNum = Math.floor(Math.random() * (max - min)) + min;
  return randomNum;
}

// 定义元素模板
const $elementTemplate = document.createElement('span');
$elementTemplate.className = 'element';

/**
 * 将原始数据数组转换为元素数组
 * @param {string[] | number[]} list 原始数据数组
 * @returns 格式化为元素数组
 */
function listToElementList(list) {
  const isMax = getType() === 'zhengTiRenDuYinJie';
  return list.map(text => {
    const $newElement = $elementTemplate.cloneNode();
    $newElement.textContent = text;
    if (isMax) {
      $newElement.className = 'element max';
    }
    return $newElement;
  });
}

// 定义行模板
const $rowTemplate = document.createElement('div');
$rowTemplate.className = 'row';

/**
 * 
 * @param {HTMLElement[]} $elementList HTML 元素数组
 * @param {number} row 行数量
 * @returns HTMLElement[] 行元素数组
 */
function listToRectangle($elementList, row) {
  const $rowList = [];
  const column = Math.ceil($elementList.length / row);

  for (let i = 0, iLimit = row, total = $elementList.length, current = 0; i < iLimit && current < total; i++) {
    const $row = $rowTemplate.cloneNode();
    for (let j = 0, jLimit = column; j < jLimit && current < total; current++, j++) {
      $row.append($elementList[current]);
    }
    $rowList.push($row);
  }
  return $rowList;
}

/**
 * 更新当前表
 */
function updateCurrentBiao() {
  let isShuZi = false;
  switch (getType()) {
    case 'ziMu':
      currentBiao = ziMuBiao;
      break;
    case 'shengMu':
      currentBiao = shengMubiao;
      break;
    case 'yunMu':
      currentBiao = yunMuBiao;
      break;
    case 'zhengTiRenDuYinJie':
      currentBiao = zhengTiRenDuYinJieBiao;
      break;
    case 'shuZi':
      currentBiao = shuZiBiao;
      isShuZi = true;
      break;
    default:
      currentBiao = ziMuBiao;
  }
  if (isShuZi) {
    $maxNumWrap.removeAttribute('hidden');
  } else {
    $maxNumWrap.setAttribute('hidden', 'hidden');
  }
}

// 监听边长变化事件
$lengthOfSide.addEventListener('change', () => {
  const total = currentBiao.length;
  let lengthOfSide = parseInt($lengthOfSide.value);
  if (total < lengthOfSide * lengthOfSide) {
    lengthOfSide = Math.floor(Math.sqrt(total));
    $lengthOfSide.value = lengthOfSide;
  }
  currentList = randomList(currentBiao, lengthOfSide);
  init();
});

// 监听最大数变化事件
$maxNum.addEventListener('change', () => {
  const maxNum = parseInt($maxNum.value || 0);
  shuZiBiao = createShuZiBiao(maxNum);
  currentBiao = shuZiBiao;
  const lengthOfSide = getLengthOfSide();
  currentList = randomList(currentBiao, lengthOfSide);
  if (getType() === 'shuZi') {
    init();
  }
});

// 监听类型切换事件
$typeSelector.addEventListener('change', () => {
  updateCurrentBiao();
  updateLengthOfSideByCurrentBiao();
  const lengthOfSide = getLengthOfSide();
  currentList = randomList(currentBiao, lengthOfSide);
  init();
});

// 监听表数量变化事件
$tableNum.addEventListener('change', () => {
  init();
});

// 监听刷新按钮点击事件
$refreshBtn.addEventListener('click', () => {
  const lengthOfSide = getLengthOfSide();
  currentList = randomList(currentBiao, lengthOfSide);
  init();
});

// 监听打印按钮点击事件
$print.addEventListener('click', () => {
  window.print();
});

function getType() {
  const index = $typeSelector.selectedIndex;
  return $typeSelector.options[index].value;
}

/**
 * 获取边长
 * @returns 边长
 */
function getLengthOfSide() {
  return parseInt($lengthOfSide.value);
}

/**
 * 根据当前数据表更新边长
 */
function updateLengthOfSideByCurrentBiao() {
  const total = currentBiao.length;
  let lengthOfSide = getLengthOfSide();
  if (total < lengthOfSide * lengthOfSide) {
    lengthOfSide = Math.floor(Math.sqrt(total));
    $lengthOfSide.value = lengthOfSide;
  }
}

/**
 * 获取表数量
 * @returns 表数量
 */
function getTableNum() {
  return parseInt($tableNum.value);
}

const $tableWrapTemplate = document.createElement('div');
$tableWrapTemplate.className = 'table-wrap';

/**
 * 初始化
 */
function init() {
  $container.innerHTML = '';
  const lengthOfSide = getLengthOfSide();
  const tableNum = getTableNum();

  $container.setAttribute('hidden', 'hidden');

  for (let i = 0, limit = tableNum; i < limit; i++) {
    const $tableWrap = $tableWrapTemplate.cloneNode();
    listToRectangle(listToElementList(shuffle(currentList)), lengthOfSide).forEach(($row) => {
      $tableWrap.append($row);
    });
    $container.append($tableWrap);
  }

  $container.removeAttribute('hidden');
}

// 初始化
const lengthOfSide = getLengthOfSide();
currentList = randomList(currentBiao, lengthOfSide);
init();
